package at.jaki.ubb.crawling.dataFinder;

import java.util.Collection;
import java.util.concurrent.Callable;

import org.apache.log4j.Logger;

import at.jaki.ubb.crawling.api.DataFinder;
import at.jaki.ubb.crawling.appThreads.AbstractManagerWrapperThread;
import at.jaki.ubb.crawling.model.DataFinderResult;
import at.jaki.ubb.crawling.model.Target;

/**
 * A Wrapper class around the DataFinder. The class implements the {@link Callable} interface, so it can be used in a multithreaded environment.
 * @author Attila Jakabfi
 *
 * @param <T> generic type of the {@link Target} element. 
 */
public class DataFinderThread<T> extends AbstractManagerWrapperThread<DataFinderResult<?, ?>> {

	private static final Logger LOG = Logger.getLogger(DataFinderThread.class);

	private DataFinder<?, ?, T> dataFinder;
	private Target<T> target;

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public DataFinderThread(String clazz) {
		try {
			Object instance = Class.forName(clazz).newInstance();
			dataFinder = (DataFinder) instance;
			dataFinder.init();
		} catch (InstantiationException e) {
			LOG.error("Could not instantiate class ".concat(clazz).concat(". No default constuctor, or the class is abstract."));
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (IllegalAccessException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (ClassNotFoundException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (ClassCastException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		} catch (RuntimeException e) {
			LOG.error(e.getClass().getName().concat(" : ") + e.getLocalizedMessage());
			if (LOG.isDebugEnabled()) {
				e.printStackTrace();
			}
		}
	}

	public final void setTarget(Target<T> target) {
		this.target = target;
	}

	public final boolean isInitialized() {
		return dataFinder != null;
	}

	public Collection<String> getTypes() {
		return dataFinder.getTypes();
	}
	
	@Override
	public DataFinderResult<?, ?> doWork() throws Exception{
		return dataFinder.findData(target);
	}

}
